#ifndef UART_COMM_H
#define UART_COMM_H

#include <stdint.h>
#include <stddef.h>

// 串口配置
#define BUF_SIZE 256 // 修改为较小的合理值

// 传输方向标识
#define FRAME_DIR_ESP32_TO_QT 0xBB    // ESP32 到 QT 方向
#define FRAME_DIR_STM32_TO_ESP32 0xCC // STM32 到 ESP32 方向
#define FRAME_DIR_ESP32_TO_STM32 0xDD // ESP32 到 STM32 方向
#define MAX_DATA_LENGTH 4             // 最大数据长度

// 命令字
#define CMD_VOLTAGE_CURRENT_SIGNAL 0x01 // 电压电流信号
#define CMD_SWITCH_SIGNAL 0x02          // 开关机信号
#define CMD_MODE_SWITCH 0x03            // 模式切换
#define CMD_PS_SETTING 0x04             // PS源模式设置参数
#define CMD_EL_SETTING 0x05             // EL载模式设置参数
#define CMD_EL_MODE_SWITCH 0x06         // EL载模式子模式切换
#define CMD_PQ_SIGNAL 0x07              // 有功无功功率信号
#define CMD_FUPF_SIGNAL 0x08            // 频率功率因数信号

// 数据编码参数结构体
typedef struct
{
    uint16_t *data;
    uint8_t data_len;
    uint8_t cmd;
    uint8_t direction;
} uart_encode_params_t;

// 解码后的帧结构体
typedef struct
{
    uint16_t data[MAX_DATA_LENGTH];
    uint8_t length;
    uint8_t cmd;
} uart_frame_t;

// 函数声明
/**
 * @brief 将数据编码成通信帧
 *
 * 该函数将uint16_t类型的数据数组编码为自定义通信帧格式。
 * 通信帧格式：帧头(1字节) + 命令字(1字节) + 数据长度(1字节) + 数据(N*2字节) + 帧尾(1字节)
 * 帧头和帧尾使用相同的值，为传输方向标识。
 *
 * @param params 包含编码所需参数的结构体指针
 * @param frame 输出参数，用于存储编码后的帧
 * @param frame_len 输出参数，用于存储编码后帧的长度
 * @return 0表示成功，-1表示参数错误，-2表示传输方向无效
 */
int uart_encode_frame(const uart_encode_params_t *params, uint8_t *frame, uint8_t *frame_len);

/**
 * @brief 将通信帧解码成数据
 *
 * 该函数将按照自定义通信帧格式解析帧数据，提取命令字和数据内容。
 * 通信帧格式：帧头(1字节) + 命令字(1字节) + 数据长度(1字节) + 数据(N*2字节) + 帧尾(1字节)
 * 函数会校验帧头和帧尾是否一致，以及帧长度是否符合预期。
 *
 * @param frame 要解码的帧数据
 * @param frame_len 帧数据长度
 * @param decoded_frame 输出参数，用于存储解码后的数据
 * @return 0表示成功，-1表示参数错误，-2表示帧头无效，-3表示帧长度错误，-4表示帧尾校验失败
 */
int uart_decode_frame(const uint8_t *frame, const uint8_t frame_len, uart_frame_t *decoded_frame);

#endif // UART_COMM_H